home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / dns / message.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  19KB  |  728 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import cStringIO
  5. import random
  6. import struct
  7. import sys
  8. import time
  9. import dns.exception as dns
  10. import dns.flags as dns
  11. import dns.name as dns
  12. import dns.opcode as dns
  13. import dns.rcode as dns
  14. import dns.rdata as dns
  15. import dns.rdataclass as dns
  16. import dns.rdatatype as dns
  17. import dns.rrset as dns
  18. import dns.renderer as dns
  19. import dns.tsig as dns
  20.  
  21. class ShortHeader(dns.exception.FormError):
  22.     pass
  23.  
  24.  
  25. class TrailingJunk(dns.exception.FormError):
  26.     pass
  27.  
  28.  
  29. class UnknownHeaderField(dns.exception.DNSException):
  30.     pass
  31.  
  32.  
  33. class BadEDNS(dns.exception.FormError):
  34.     pass
  35.  
  36.  
  37. class BadTSIG(dns.exception.FormError):
  38.     pass
  39.  
  40.  
  41. class UnknownTSIGKey(dns.exception.DNSException):
  42.     pass
  43.  
  44.  
  45. class Message(object):
  46.     
  47.     def __init__(self, id = None):
  48.         if id is None:
  49.             self.id = random.randint(0, 65535)
  50.         else:
  51.             self.id = id
  52.         self.flags = 0
  53.         self.question = []
  54.         self.answer = []
  55.         self.authority = []
  56.         self.additional = []
  57.         self.edns = -1
  58.         self.ednsflags = 0
  59.         self.payload = 0
  60.         self.request_payload = 0
  61.         self.keyring = None
  62.         self.keyname = None
  63.         self.request_mac = ''
  64.         self.other_data = ''
  65.         self.tsig_error = 0
  66.         self.fudge = 300
  67.         self.original_id = self.id
  68.         self.mac = ''
  69.         self.xfr = False
  70.         self.origin = None
  71.         self.tsig_ctx = None
  72.         self.had_tsig = False
  73.         self.multi = False
  74.         self.first = True
  75.         self.index = { }
  76.  
  77.     
  78.     def __repr__(self):
  79.         return '<DNS message, ID ' + `self.id` + '>'
  80.  
  81.     
  82.     def __str__(self):
  83.         return self.to_text()
  84.  
  85.     
  86.     def to_text(self, origin = None, relativize = True, **kw):
  87.         s = cStringIO.StringIO()
  88.         print >>s, 'id %d' % self.id
  89.         print >>s, 'opcode %s' % dns.opcode.to_text(dns.opcode.from_flags(self.flags))
  90.         rc = dns.rcode.from_flags(self.flags, self.ednsflags)
  91.         print >>s, 'rcode %s' % dns.rcode.to_text(rc)
  92.         print >>s, 'flags %s' % dns.flags.to_text(self.flags)
  93.         if self.edns >= 0:
  94.             print >>s, 'edns %s' % self.edns
  95.             if self.ednsflags != 0:
  96.                 print >>s, 'eflags %s' % dns.flags.edns_to_text(self.ednsflags)
  97.             
  98.             print >>s, 'payload', self.payload
  99.         
  100.         is_update = dns.opcode.is_update(self.flags)
  101.         if is_update:
  102.             print >>s, ';ZONE'
  103.         else:
  104.             print >>s, ';QUESTION'
  105.         for rrset in self.question:
  106.             print >>s, rrset.to_text(origin, relativize, **kw)
  107.         
  108.         if is_update:
  109.             print >>s, ';PREREQ'
  110.         else:
  111.             print >>s, ';ANSWER'
  112.         for rrset in self.answer:
  113.             print >>s, rrset.to_text(origin, relativize, **kw)
  114.         
  115.         if is_update:
  116.             print >>s, ';UPDATE'
  117.         else:
  118.             print >>s, ';AUTHORITY'
  119.         for rrset in self.authority:
  120.             print >>s, rrset.to_text(origin, relativize, **kw)
  121.         
  122.         print >>s, ';ADDITIONAL'
  123.         for rrset in self.additional:
  124.             print >>s, rrset.to_text(origin, relativize, **kw)
  125.         
  126.         return s.getvalue()[:-1]
  127.  
  128.     
  129.     def __eq__(self, other):
  130.         if not isinstance(other, Message):
  131.             return False
  132.         
  133.         if self.id != other.id:
  134.             return False
  135.         
  136.         if self.flags != other.flags:
  137.             return False
  138.         
  139.         for n in self.question:
  140.             if n not in other.question:
  141.                 return False
  142.                 continue
  143.         
  144.         for n in other.question:
  145.             if n not in self.question:
  146.                 return False
  147.                 continue
  148.         
  149.         for n in self.answer:
  150.             if n not in other.answer:
  151.                 return False
  152.                 continue
  153.         
  154.         for n in other.answer:
  155.             if n not in self.answer:
  156.                 return False
  157.                 continue
  158.         
  159.         for n in self.authority:
  160.             if n not in other.authority:
  161.                 return False
  162.                 continue
  163.         
  164.         for n in other.authority:
  165.             if n not in self.authority:
  166.                 return False
  167.                 continue
  168.         
  169.         return True
  170.  
  171.     
  172.     def __ne__(self, other):
  173.         return not self.__eq__(other)
  174.  
  175.     
  176.     def is_response(self, other):
  177.         if other.flags & dns.flags.QR == 0 and self.id != other.id or dns.opcode.from_flags(self.flags) != dns.opcode.from_flags(other.flags):
  178.             return False
  179.         
  180.         if dns.rcode.from_flags(other.flags, other.ednsflags) != dns.rcode.NOERROR:
  181.             return True
  182.         
  183.         if dns.opcode.is_update(self.flags):
  184.             return True
  185.         
  186.         for n in self.question:
  187.             if n not in other.question:
  188.                 return False
  189.                 continue
  190.         
  191.         for n in other.question:
  192.             if n not in self.question:
  193.                 return False
  194.                 continue
  195.         
  196.         return True
  197.  
  198.     
  199.     def section_number(self, section):
  200.         if section is self.question:
  201.             return 0
  202.         elif section is self.answer:
  203.             return 1
  204.         elif section is self.authority:
  205.             return 2
  206.         elif section is self.additional:
  207.             return 3
  208.         else:
  209.             raise ValueError, 'unknown section'
  210.  
  211.     
  212.     def find_rrset(self, section, name, rdclass, rdtype, covers = dns.rdatatype.NONE, deleting = None, create = False, force_unique = False):
  213.         key = (self.section_number(section), name, rdclass, rdtype, covers, deleting)
  214.         if not force_unique:
  215.             if self.index is not None:
  216.                 rrset = self.index.get(key)
  217.                 if rrset is not None:
  218.                     return rrset
  219.                 
  220.             else:
  221.                 for rrset in section:
  222.                     if rrset.match(name, rdclass, rdtype, covers, deleting):
  223.                         return rrset
  224.                         continue
  225.                 
  226.         
  227.         if not create:
  228.             raise KeyError
  229.         
  230.         rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
  231.         section.append(rrset)
  232.         if self.index is not None:
  233.             self.index[key] = rrset
  234.         
  235.         return rrset
  236.  
  237.     
  238.     def get_rrset(self, section, name, rdclass, rdtype, covers = dns.rdatatype.NONE, deleting = None, create = False, force_unique = False):
  239.         
  240.         try:
  241.             rrset = self.find_rrset(section, name, rdclass, rdtype, covers, deleting, create, force_unique)
  242.         except KeyError:
  243.             rrset = None
  244.  
  245.         return rrset
  246.  
  247.     
  248.     def to_wire(self, origin = None, max_size = 0, **kw):
  249.         if max_size == 0:
  250.             if self.request_payload != 0:
  251.                 max_size = self.request_payload
  252.             else:
  253.                 max_size = 65535
  254.         
  255.         if max_size < 512:
  256.             max_size = 512
  257.         elif max_size > 65535:
  258.             max_size = 65535
  259.         
  260.         r = dns.renderer.Renderer(self.id, self.flags, max_size, origin)
  261.         for rrset in self.question:
  262.             r.add_question(rrset.name, rrset.rdtype, rrset.rdclass)
  263.         
  264.         for rrset in self.answer:
  265.             r.add_rrset(dns.renderer.ANSWER, rrset, **kw)
  266.         
  267.         for rrset in self.authority:
  268.             r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw)
  269.         
  270.         if self.edns >= 0:
  271.             r.add_edns(self.edns, self.ednsflags, self.payload)
  272.         
  273.         for rrset in self.additional:
  274.             r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
  275.         
  276.         r.write_header()
  277.         if self.keyname is not None:
  278.             r.add_tsig(self.keyname, self.keyring[self.keyname], self.fudge, self.original_id, self.tsig_error, self.other_data, self.request_mac)
  279.             self.mac = r.mac
  280.         
  281.         return r.get_wire()
  282.  
  283.     
  284.     def use_tsig(self, keyring, keyname = None, fudge = 300, original_id = None, tsig_error = 0, other_data = ''):
  285.         self.keyring = keyring
  286.         if keyname is None:
  287.             self.keyname = self.keyring.keys()[0]
  288.         elif isinstance(keyname, (str, unicode)):
  289.             keyname = dns.name.from_text(keyname)
  290.         
  291.         self.keyname = keyname
  292.         self.fudge = fudge
  293.         if original_id is None:
  294.             self.original_id = self.id
  295.         else:
  296.             self.original_id = original_id
  297.         self.tsig_error = tsig_error
  298.         self.other_data = other_data
  299.  
  300.     
  301.     def use_edns(self, edns = 0, ednsflags = 0, payload = 1280, request_payload = None):
  302.         if edns is None or edns is False:
  303.             edns = -1
  304.         
  305.         if edns is True:
  306.             edns = 0
  307.         
  308.         if request_payload is None:
  309.             request_payload = payload
  310.         
  311.         if edns < 0:
  312.             ednsflags = 0
  313.             payload = 0
  314.             request_payload = 0
  315.         else:
  316.             ednsflags &= 0xFF00FFFFL
  317.             ednsflags |= edns << 16
  318.         self.edns = edns
  319.         self.ednsflags = ednsflags
  320.         self.payload = payload
  321.         self.request_payload = request_payload
  322.  
  323.     
  324.     def want_dnssec(self, wanted = True):
  325.         if wanted:
  326.             if self.edns < 0:
  327.                 self.use_edns()
  328.             
  329.             self.ednsflags |= dns.flags.DO
  330.         elif self.edns >= 0:
  331.             self.ednsflags &= ~(dns.flags.DO)
  332.         
  333.  
  334.     
  335.     def rcode(self):
  336.         return dns.rcode.from_flags(self.flags, self.ednsflags)
  337.  
  338.     
  339.     def set_rcode(self, rcode):
  340.         (value, evalue) = dns.rcode.to_flags(rcode)
  341.         self.flags &= 65520
  342.         self.flags |= value
  343.         self.ednsflags &= 0xFFFFFFL
  344.         self.ednsflags |= evalue
  345.  
  346.     
  347.     def opcode(self):
  348.         return dns.opcode.from_flags(self.flags)
  349.  
  350.     
  351.     def set_opcode(self, opcode):
  352.         self.flags &= 34815
  353.         self.flags |= dns.opcode.to_flags(opcode)
  354.  
  355.  
  356.  
  357. class _WireReader(object):
  358.     
  359.     def __init__(self, wire, message, question_only = False):
  360.         self.wire = wire
  361.         self.message = message
  362.         self.current = 0
  363.         self.updating = False
  364.         self.zone_rdclass = dns.rdataclass.IN
  365.         self.question_only = question_only
  366.  
  367.     
  368.     def _get_question(self, qcount):
  369.         if self.updating and qcount > 1:
  370.             raise dns.exception.FormError
  371.         
  372.         for i in xrange(0, qcount):
  373.             (qname, used) = dns.name.from_wire(self.wire, self.current)
  374.             if self.message.origin is not None:
  375.                 qname = qname.relativize(self.message.origin)
  376.             
  377.             self.current = self.current + used
  378.             (rdtype, rdclass) = struct.unpack('!HH', self.wire[self.current:self.current + 4])
  379.             self.current = self.current + 4
  380.             self.message.find_rrset(self.message.question, qname, rdclass, rdtype, create = True, force_unique = True)
  381.             if self.updating:
  382.                 self.zone_rdclass = rdclass
  383.                 continue
  384.         
  385.  
  386.     
  387.     def _get_section(self, section, count):
  388.         if self.updating:
  389.             force_unique = True
  390.         else:
  391.             force_unique = False
  392.         seen_opt = False
  393.         for i in xrange(0, count):
  394.             rr_start = self.current
  395.             (name, used) = dns.name.from_wire(self.wire, self.current)
  396.             if self.message.origin is not None:
  397.                 name = name.relativize(self.message.origin)
  398.             
  399.             self.current = self.current + used
  400.             (rdtype, rdclass, ttl, rdlen) = struct.unpack('!HHIH', self.wire[self.current:self.current + 10])
  401.             self.current = self.current + 10
  402.             if rdtype == dns.rdatatype.OPT:
  403.                 if section is not self.message.additional or seen_opt:
  404.                     raise BadEDNS
  405.                 
  406.                 self.message.payload = rdclass
  407.                 self.message.ednsflags = ttl
  408.                 self.message.edns = (ttl & 16711680) >> 16
  409.                 seen_opt = True
  410.             elif rdtype == dns.rdatatype.TSIG:
  411.                 if not section is self.message.additional and i == count - 1:
  412.                     raise BadTSIG
  413.                 
  414.                 if self.message.keyring is None:
  415.                     raise UnknownTSIGKey, 'got signed message without keyring'
  416.                 
  417.                 secret = self.message.keyring.get(name)
  418.                 if secret is None:
  419.                     raise UnknownTSIGKey, "key '%s' unknown" % name
  420.                 
  421.                 self.message.tsig_ctx = dns.tsig.validate(self.wire, name, secret, int(time.time()), self.message.request_mac, rr_start, self.current, rdlen, self.message.tsig_ctx, self.message.multi, self.message.first)
  422.                 self.message.had_tsig = True
  423.             elif ttl < 0:
  424.                 ttl = 0
  425.             
  426.             if self.updating:
  427.                 if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE:
  428.                     deleting = rdclass
  429.                     rdclass = self.zone_rdclass
  430.                 else:
  431.                     deleting = None
  432.             if deleting == dns.rdataclass.ANY:
  433.                 covers = dns.rdatatype.NONE
  434.                 rd = None
  435.             else:
  436.                 rd = dns.rdata.from_wire(rdclass, rdtype, self.wire, self.current, rdlen, self.message.origin)
  437.                 covers = rd.covers()
  438.             if self.message.xfr and rdtype == dns.rdatatype.SOA:
  439.                 force_unique = True
  440.             
  441.             rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique)
  442.             if rd is not None:
  443.                 rrset.add(rd, ttl)
  444.             
  445.             self.current = self.current + rdlen
  446.         
  447.  
  448.     
  449.     def read(self):
  450.         l = len(self.wire)
  451.         if l < 12:
  452.             raise ShortHeader
  453.         
  454.         (self.message.id, self.message.flags, qcount, ancount, aucount, adcount) = struct.unpack('!HHHHHH', self.wire[:12])
  455.         self.current = 12
  456.         if dns.opcode.is_update(self.message.flags):
  457.             self.updating = True
  458.         
  459.         self._get_question(qcount)
  460.         if self.question_only:
  461.             return None
  462.         
  463.         self._get_section(self.message.answer, ancount)
  464.         self._get_section(self.message.authority, aucount)
  465.         self._get_section(self.message.additional, adcount)
  466.         if self.current != l:
  467.             raise TrailingJunk
  468.         
  469.         if self.message.multi and self.message.tsig_ctx and not (self.message.had_tsig):
  470.             self.message.tsig_ctx.update(self.wire)
  471.         
  472.  
  473.  
  474.  
  475. def from_wire(wire, keyring = None, request_mac = '', xfr = False, origin = None, tsig_ctx = None, multi = False, first = True, question_only = False):
  476.     m = Message(id = 0)
  477.     m.keyring = keyring
  478.     m.request_mac = request_mac
  479.     m.xfr = xfr
  480.     m.origin = origin
  481.     m.tsig_ctx = tsig_ctx
  482.     m.multi = multi
  483.     m.first = first
  484.     reader = _WireReader(wire, m, question_only)
  485.     reader.read()
  486.     return m
  487.  
  488.  
  489. class _TextReader(object):
  490.     
  491.     def __init__(self, text, message):
  492.         self.message = message
  493.         self.tok = dns.tokenizer.Tokenizer(text)
  494.         self.last_name = None
  495.         self.zone_rdclass = dns.rdataclass.IN
  496.         self.updating = False
  497.  
  498.     
  499.     def _header_line(self, section):
  500.         (ttype, what) = self.tok.get()
  501.         if what == 'id':
  502.             self.message.id = self.tok.get_int()
  503.         elif what == 'flags':
  504.             while True:
  505.                 token = self.tok.get()
  506.                 if token[0] != dns.tokenizer.IDENTIFIER:
  507.                     self.tok.unget(token)
  508.                     break
  509.                 
  510.                 self.message.flags = self.message.flags | dns.flags.from_text(token[1])
  511.             if dns.opcode.is_update(self.message.flags):
  512.                 self.updating = True
  513.             
  514.         elif what == 'edns':
  515.             self.message.edns = self.tok.get_int()
  516.             self.message.ednsflags = self.message.ednsflags | self.message.edns << 16
  517.         elif what == 'eflags':
  518.             if self.message.edns < 0:
  519.                 self.message.edns = 0
  520.             
  521.             while True:
  522.                 token = self.tok.get()
  523.                 if token[0] != dns.tokenizer.IDENTIFIER:
  524.                     self.tok.unget(token)
  525.                     break
  526.                 
  527.                 self.message.ednsflags = self.message.ednsflags | dns.flags.edns_from_text(token[1])
  528.         elif what == 'payload':
  529.             self.message.payload = self.tok.get_int()
  530.             if self.message.edns < 0:
  531.                 self.message.edns = 0
  532.             
  533.         elif what == 'opcode':
  534.             text = self.tok.get_string()
  535.             self.message.flags = self.message.flags | dns.opcode.to_flags(dns.opcode.from_text(text))
  536.         elif what == 'rcode':
  537.             text = self.tok.get_string()
  538.             self.message.set_rcode(dns.rcode.from_text(text))
  539.         else:
  540.             raise UnknownHeaderField
  541.         self.tok.get_eol()
  542.  
  543.     
  544.     def _question_line(self, section):
  545.         token = self.tok.get(want_leading = True)
  546.         if token[0] != dns.tokenizer.WHITESPACE:
  547.             self.last_name = dns.name.from_text(token[1], None)
  548.         
  549.         name = self.last_name
  550.         token = self.tok.get()
  551.         if token[0] != dns.tokenizer.IDENTIFIER:
  552.             raise dns.exception.SyntaxError
  553.         
  554.         
  555.         try:
  556.             rdclass = dns.rdataclass.from_text(token[1])
  557.             token = self.tok.get()
  558.             if token[0] != dns.tokenizer.IDENTIFIER:
  559.                 raise dns.exception.SyntaxError
  560.         except dns.exception.SyntaxError:
  561.             raise dns.exception.SyntaxError
  562.         except:
  563.             rdclass = dns.rdataclass.IN
  564.  
  565.         rdtype = dns.rdatatype.from_text(token[1])
  566.         self.message.find_rrset(self.message.question, name, rdclass, rdtype, create = True, force_unique = True)
  567.         if self.updating:
  568.             self.zone_rdclass = rdclass
  569.         
  570.         self.tok.get_eol()
  571.  
  572.     
  573.     def _rr_line(self, section):
  574.         deleting = None
  575.         token = self.tok.get(want_leading = True)
  576.         if token[0] != dns.tokenizer.WHITESPACE:
  577.             self.last_name = dns.name.from_text(token[1], None)
  578.         
  579.         name = self.last_name
  580.         token = self.tok.get()
  581.         if token[0] != dns.tokenizer.IDENTIFIER:
  582.             raise dns.exception.SyntaxError
  583.         
  584.         
  585.         try:
  586.             ttl = int(token[1], 0)
  587.             token = self.tok.get()
  588.             if token[0] != dns.tokenizer.IDENTIFIER:
  589.                 raise dns.exception.SyntaxError
  590.         except dns.exception.SyntaxError:
  591.             raise dns.exception.SyntaxError
  592.         except:
  593.             ttl = 0
  594.  
  595.         
  596.         try:
  597.             rdclass = dns.rdataclass.from_text(token[1])
  598.             token = self.tok.get()
  599.             if token[0] != dns.tokenizer.IDENTIFIER:
  600.                 raise dns.exception.SyntaxError
  601.             
  602.             if rdclass == dns.rdataclass.ANY or rdclass == dns.rdataclass.NONE:
  603.                 deleting = rdclass
  604.                 rdclass = self.zone_rdclass
  605.         except dns.exception.SyntaxError:
  606.             raise dns.exception.SyntaxError
  607.         except:
  608.             rdclass = dns.rdataclass.IN
  609.  
  610.         rdtype = dns.rdatatype.from_text(token[1])
  611.         token = self.tok.get()
  612.         if token[0] != dns.tokenizer.EOL and token[0] != dns.tokenizer.EOF:
  613.             self.tok.unget(token)
  614.             rd = dns.rdata.from_text(rdclass, rdtype, self.tok, None)
  615.             covers = rd.covers()
  616.         else:
  617.             rd = None
  618.             covers = dns.rdatatype.NONE
  619.         rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, self.updating)
  620.         if rd is not None:
  621.             rrset.add(rd, ttl)
  622.         
  623.  
  624.     
  625.     def read(self):
  626.         line_method = self._header_line
  627.         section = None
  628.         while None:
  629.             token = self.tok.get(True, True)
  630.             if token[0] == dns.tokenizer.EOL or token[0] == dns.tokenizer.EOF:
  631.                 break
  632.             
  633.             if token[0] == dns.tokenizer.COMMENT:
  634.                 u = token[1].upper()
  635.                 if u == 'HEADER':
  636.                     line_method = self._header_line
  637.                 elif u == 'QUESTION' or u == 'ZONE':
  638.                     line_method = self._question_line
  639.                     section = self.message.question
  640.                 elif u == 'ANSWER' or u == 'PREREQ':
  641.                     line_method = self._rr_line
  642.                     section = self.message.answer
  643.                 elif u == 'AUTHORITY' or u == 'UPDATE':
  644.                     line_method = self._rr_line
  645.                     section = self.message.authority
  646.                 elif u == 'ADDITIONAL':
  647.                     line_method = self._rr_line
  648.                     section = self.message.additional
  649.                 
  650.                 self.tok.get_eol()
  651.                 continue
  652.             
  653.             line_method(section)
  654.             continue
  655.             return None
  656.  
  657.  
  658.  
  659. def from_text(text):
  660.     m = Message()
  661.     reader = _TextReader(text, m)
  662.     reader.read()
  663.     return m
  664.  
  665.  
  666. def from_file(f):
  667.     if sys.hexversion >= 33751040:
  668.         str_type = basestring
  669.         opts = 'rU'
  670.     else:
  671.         str_type = str
  672.         opts = 'r'
  673.     if isinstance(f, str_type):
  674.         f = file(f, opts)
  675.         want_close = True
  676.     else:
  677.         want_close = False
  678.     
  679.     try:
  680.         m = from_text(f)
  681.     finally:
  682.         if want_close:
  683.             f.close()
  684.         
  685.  
  686.     return m
  687.  
  688.  
  689. def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns = None, want_dnssec = False):
  690.     if isinstance(qname, (str, unicode)):
  691.         qname = dns.name.from_text(qname)
  692.     
  693.     if isinstance(rdtype, str):
  694.         rdtype = dns.rdatatype.from_text(rdtype)
  695.     
  696.     if isinstance(rdclass, str):
  697.         rdclass = dns.rdataclass.from_text(rdclass)
  698.     
  699.     m = Message()
  700.     m.flags |= dns.flags.RD
  701.     m.find_rrset(m.question, qname, rdclass, rdtype, create = True, force_unique = True)
  702.     m.use_edns(use_edns)
  703.     m.want_dnssec(want_dnssec)
  704.     return m
  705.  
  706.  
  707. def make_response(query, recursion_available = False, our_payload = 8192):
  708.     if query.flags & dns.flags.QR:
  709.         raise dns.exception.FormError, 'specified query message is not a query'
  710.     
  711.     response = dns.message.Message(query.id)
  712.     response.flags = dns.flags.QR | query.flags & dns.flags.RD
  713.     if recursion_available:
  714.         response.flags |= dns.flags.RA
  715.     
  716.     response.set_opcode(query.opcode())
  717.     response.question = list(query.question)
  718.     if query.edns >= 0:
  719.         response.use_edns(0, 0, our_payload, query.payload)
  720.     
  721.     if query.keyname is not None:
  722.         response.keyname = query.keyname
  723.         response.keyring = query.keyring
  724.         response.request_mac = query.mac
  725.     
  726.     return response
  727.  
  728.